package com.example.springboot2.service;

import com.example.springboot2.common.PageResult;
import com.example.springboot2.entity.Merchant;
import com.example.springboot2.entity.Order;
import com.example.springboot2.exception.BusinessException;
import com.example.springboot2.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import jakarta.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 订单服务类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository orderRepository;
    private final MerchantService merchantService;

    /**
     * 根据ID查找订单
     */
    public Order findById(Long id) {
        return orderRepository.findById(id)
                .orElseThrow(() -> new BusinessException("订单不存在"));
    }

    /**
     * 分页查询订单列表
     */
    public PageResult<Order> getOrdersList(Long userId, Integer current, Integer size, 
                                           String orderNo, String status, String orderType) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        
        Pageable pageable = PageRequest.of(current - 1, size, 
                Sort.by(Sort.Direction.DESC, "createdTime"));
        
        Specification<Order> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 商家条件
            predicates.add(criteriaBuilder.equal(root.get("merchant"), merchant));
            
            // 订单号查询
            if (StringUtils.hasText(orderNo)) {
                predicates.add(criteriaBuilder.like(root.get("orderNo"), "%" + orderNo + "%"));
            }
            
            // 状态查询
            if (StringUtils.hasText(status)) {
                predicates.add(criteriaBuilder.equal(root.get("status"), Order.OrderStatus.valueOf(status)));
            }
            
            // 订单类型查询
            if (StringUtils.hasText(orderType)) {
                predicates.add(criteriaBuilder.equal(root.get("orderType"), Order.OrderType.valueOf(orderType)));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        Page<Order> page = orderRepository.findAll(spec, pageable);
        return PageResult.of(page);
    }

    /**
     * 获取订单详情
     */
    public Order getOrderDetail(Long userId, Long orderId) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        Order order = findById(orderId);
        
        // 验证订单是否属于当前商家
        if (!order.getMerchant().getId().equals(merchant.getId())) {
            throw new BusinessException("无权访问该订单");
        }
        
        return order;
    }

    /**
     * 更新订单状态
     */
    @Transactional
    public void updateOrderStatus(Long userId, Long orderId, Order.OrderStatus status, 
                                  String logisticsCompany, String trackingNumber, String remark) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        Order order = findById(orderId);
        
        // 验证订单是否属于当前商家
        if (!order.getMerchant().getId().equals(merchant.getId())) {
            throw new BusinessException("无权修改该订单");
        }
        
        // 更新订单状态
        Order.OrderStatus oldStatus = order.getStatus();
        order.setStatus(status);
        
        // 根据状态更新相应的时间字段
        LocalDateTime now = LocalDateTime.now();
        switch (status) {
            case SHIPPED:
                order.setShippingTime(now);
                order.setLogisticsCompany(logisticsCompany);
                order.setTrackingNumber(trackingNumber);
                break;
            case DELIVERED:
                order.setDeliveryTime(now);
                break;
            case FINISHED:
                order.setFinishTime(now);
                break;
            case CANCELLED:
                order.setCancelTime(now);
                order.setCancelReason(remark);
                break;
        }
        
        if (StringUtils.hasText(remark)) {
            order.setRemark(remark);
        }
        
        orderRepository.save(order);
        
        log.info("商家更新订单状态: {} - 订单号: {} - {} -> {}", 
                merchant.getShopName(), order.getOrderNo(), oldStatus, status);
    }

    /**
     * 取消订单
     */
    @Transactional
    public void cancelOrder(Long userId, Long orderId, String reason) {
        updateOrderStatus(userId, orderId, Order.OrderStatus.CANCELLED, null, null, reason);
    }

    /**
     * 获取订单统计数据
     */
    public OrderStats getOrderStats(Long userId) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        
        long totalCount = orderRepository.countByMerchant(merchant);
        long pendingCount = orderRepository.countByMerchantAndStatus(merchant, Order.OrderStatus.PENDING);
        long paidCount = orderRepository.countByMerchantAndStatus(merchant, Order.OrderStatus.PAID);
        long shippedCount = orderRepository.countByMerchantAndStatus(merchant, Order.OrderStatus.SHIPPED);
        long deliveredCount = orderRepository.countByMerchantAndStatus(merchant, Order.OrderStatus.DELIVERED);
        long finishedCount = orderRepository.countByMerchantAndStatus(merchant, Order.OrderStatus.FINISHED);
        long cancelledCount = orderRepository.countByMerchantAndStatus(merchant, Order.OrderStatus.CANCELLED);
        
        return OrderStats.builder()
                .totalCount(totalCount)
                .pendingCount(pendingCount)
                .paidCount(paidCount)
                .shippedCount(shippedCount)
                .deliveredCount(deliveredCount)
                .finishedCount(finishedCount)
                .cancelledCount(cancelledCount)
                .build();
    }

    /**
     * 获取今日订单
     */
    public List<Order> getTodayOrders(Long userId) {
        Merchant merchant = merchantService.getMerchantInfo(userId);
        return orderRepository.findTodayOrdersByMerchant(merchant);
    }

    /**
     * 订单统计数据DTO
     */
    @lombok.Data
    @lombok.Builder
    public static class OrderStats {
        private Long totalCount;
        private Long pendingCount;
        private Long paidCount;
        private Long shippedCount;
        private Long deliveredCount;
        private Long finishedCount;
        private Long cancelledCount;
    }
}
